<template>
  <div class="role-management">
    <div class="page-header">
      <h2>角色管理</h2>
      <div class="header-actions">
        <el-button 
          v-if="hasPermission('role:add')"
          type="primary" 
          @click="handleAdd"
        >
          <el-icon><Plus /></el-icon>
          新增角色
        </el-button>
      </div>
    </div>

    <div class="table-container">
      <el-table :data="roles" v-loading="loading" stripe>
        <el-table-column prop="id" label="ID" width="80" />
        <el-table-column prop="roleName" label="角色名称" />
        <el-table-column prop="roleCode" label="角色编码" />
        <el-table-column prop="description" label="描述" />
        <el-table-column prop="status" label="状态" width="100">
          <template #default="{ row }">
            <el-tag :type="row.status === 1 ? 'success' : 'danger'">
              {{ row.status === 1 ? '启用' : '禁用' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="createTime" label="创建时间" width="180">
          <template #default="{ row }">
            {{ formatDate(row.createTime) }}
          </template>
        </el-table-column>
        <el-table-column label="操作" width="300">
          <template #default="{ row }">
            <el-button 
              v-if="hasPermission('role:edit')"
              type="primary" 
              size="small" 
              @click="handleEdit(row)"
            >
              编辑
            </el-button>
            <el-button 
              v-if="hasPermission('role:assign-menu')"
              type="warning" 
              size="small" 
              @click="handleAssignMenu(row)"
            >
              分配菜单
            </el-button>
            <el-button 
              v-if="hasPermission('role:assign-permission')"
              type="info" 
              size="small" 
              @click="handleAssignPermission(row)"
            >
              分配权限
            </el-button>
            <el-button 
              v-if="hasPermission('role:delete')"
              type="danger" 
              size="small" 
              @click="handleDelete(row)"
            >
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>

    <!-- 新增/编辑角色对话框 -->
    <el-dialog v-model="roleDialogVisible" :title="isEdit ? '编辑角色' : '新增角色'" width="500px">
      <el-form :model="roleForm" :rules="roleRules" ref="roleFormRef" label-width="80px">
        <el-form-item label="角色名称" prop="roleName">
          <el-input v-model="roleForm.roleName" placeholder="请输入角色名称" />
        </el-form-item>
        <el-form-item label="角色编码" prop="roleCode">
          <el-input v-model="roleForm.roleCode" placeholder="请输入角色编码（如：ADMIN、USER）" />
        </el-form-item>
        <el-form-item label="角色描述" prop="description">
          <el-input 
            v-model="roleForm.description" 
            type="textarea" 
            :rows="3" 
            placeholder="请输入角色描述" 
          />
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-select v-model="roleForm.status" placeholder="请选择状态">
            <el-option label="启用" :value="1" />
            <el-option label="禁用" :value="0" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="closeRoleDialog">取消</el-button>
        <el-button type="primary" @click="confirmRole" :loading="roleLoading">
          确定
        </el-button>
      </template>
    </el-dialog>

    <!-- 分配菜单权限对话框 -->
    <el-dialog 
      v-model="assignMenuVisible" 
      title="分配菜单权限" 
      width="600px" 
      @opened="onDialogOpened"
      :close-on-click-modal="false"
    >
      <div class="assign-menu-content">
        <div class="role-info">
          <span>角色：{{ assignMenuForm.roleName }}</span>
        </div>
        <div class="menu-info">
          <el-alert
            title="自动权限绑定"
            type="info"
            description="分配菜单时会自动分配菜单对应的操作权限"
            :closable="false"
            show-icon
            style="margin-bottom: 15px;"
          />
        </div>
        <el-tree
          ref="menuTreeRef"
          :data="menuTreeData"
          :props="treeProps"
          show-checkbox
          node-key="id"
          class="menu-tree"
        >
          <template #default="{ node, data }">
            <div class="tree-node-content">
              <span class="node-label">{{ data.menuName }}</span>
              <el-tag 
                v-if="data.menuType === 'BUTTON'" 
                type="info" 
                size="small" 
                class="node-type-tag"
              >
                按钮
              </el-tag>
              <el-tag 
                v-else-if="data.menuType === 'DIRECTORY'" 
                type="warning" 
                size="small" 
                class="node-type-tag"
              >
                目录
              </el-tag>
              <el-tag 
                v-else 
                type="success" 
                size="small" 
                class="node-type-tag"
              >
                菜单
              </el-tag>
            </div>
          </template>
        </el-tree>
        
        <!-- 底部按钮 -->
        <div style="margin-top: 20px; text-align: right;">
          <el-button @click="closeAssignDialog">取消</el-button>
          <el-button type="primary" @click="confirmAssignMenu" :loading="assignLoading">
            确定
          </el-button>
        </div>
      </div>
    </el-dialog>

    <!-- 分配权限对话框 -->
    <el-dialog v-model="assignPermissionVisible" title="分配权限" width="700px" @opened="onPermissionDialogOpened">
      <div class="assign-permission-content">
        <div class="role-info">
          <span>角色：{{ assignPermissionForm.roleName }}</span>
        </div>
        <el-tree
          ref="permissionTreeRef"
          :data="permissionTreeData"
          :props="permissionTreeProps"
          show-checkbox
          node-key="id"
          class="permission-tree"
          default-expand-all
        >
          <template #default="{ node, data }">
            <div class="permission-tree-node-content">
              <span class="permission-node-label">{{ data.permissionName }}</span>
              <el-tag 
                :type="getPermissionTypeTag(data.permissionType)"
                size="small" 
                class="permission-node-type-tag"
              >
                {{ getPermissionTypeName(data.permissionType) }}
              </el-tag>
              <code v-if="data.permissionCode" class="permission-code-tag">{{ data.permissionCode }}</code>
            </div>
          </template>
        </el-tree>
      </div>
      <template #footer>
        <el-button @click="closeAssignPermissionDialog">取消</el-button>
        <el-button type="primary" @click="confirmAssignPermission" :loading="assignPermissionLoading">
          确定
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, onMounted, reactive, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import request from '../utils/request'
import { usePermissions } from '../stores/permission'
    const roles = ref([])
    const loading = ref(false)
    const roleDialogVisible = ref(false)
    const roleLoading = ref(false)
    const isEdit = ref(false)
    const roleFormRef = ref()
    const assignMenuVisible = ref(false)
    const assignLoading = ref(false)
    const menuTreeRef = ref()
    const menuTreeData = ref([])
    const checkedMenuIds = ref([])
    
    // 权限分配相关状态
    const assignPermissionVisible = ref(false)
    const assignPermissionLoading = ref(false)
    const permissionTreeRef = ref()
    const permissionTreeData = ref([])
    const checkedPermissionIds = ref([])
    
    const roleForm = reactive({
      id: null,
      roleName: '',
      roleCode: '',
      description: '',
      status: 1
    })
    
    const assignMenuForm = reactive({
      roleId: null,
      roleName: ''
    })
    
    const assignPermissionForm = reactive({
      roleId: null,
      roleName: ''
    })

    const treeProps = {
      children: 'children',
      label: 'menuName'
    }
    
    const permissionTreeProps = {
      children: 'children',
      label: 'permissionName'
    }

    // 表单验证规则
    const roleRules = {
      roleName: [
        { required: true, message: '请输入角色名称', trigger: 'blur' },
        { min: 2, max: 20, message: '角色名称长度在 2 到 20 个字符', trigger: 'blur' }
      ],
      roleCode: [
        { required: true, message: '请输入角色编码', trigger: 'blur' },
        { min: 2, max: 20, message: '角色编码长度在 2 到 20 个字符', trigger: 'blur' },
        { pattern: /^[A-Z_]+$/, message: '角色编码只能包含大写字母和下划线', trigger: 'blur' }
      ],
      description: [
        { max: 200, message: '描述长度不能超过 200 个字符', trigger: 'blur' }
      ],
      status: [
        { required: true, message: '请选择状态', trigger: 'change' }
      ]
    }

    // 使用响应式权限检查
    const { hasPermission } = usePermissions()

    // 格式化日期
    const formatDate = (dateString) => {
      if (!dateString) return ''
      return new Date(dateString).toLocaleString('zh-CN')
    }

    // 获取权限类型标签样式
    const getPermissionTypeTag = (type) => {
      switch (type) {
        case 'MENU': return 'success'
        case 'OPERATION': return 'primary'
        case 'DATA': return 'warning'
        case 'API': return 'danger'
        case 'BUTTON': return 'info'
        default: return 'info'
      }
    }

    // 获取权限类型名称
    const getPermissionTypeName = (type) => {
      switch (type) {
        case 'MENU': return '菜单'
        case 'OPERATION': return '操作'
        case 'DATA': return '数据'
        case 'API': return '接口'
        case 'BUTTON': return '按钮'
        default: return '未知'
      }
    }

    // 获取角色列表
    const fetchRoles = async () => {
      try {
        loading.value = true
        const response = await request.get('/admin/roles')
        roles.value = response.data
      } catch (error) {
        console.error('获取角色列表失败:', error)
        ElMessage.error('获取角色列表失败')
      } finally {
        loading.value = false
      }
    }

    // 获取菜单树数据
    const fetchMenuTree = async () => {
      try {
        const response = await request.get('/admin/menus')
        menuTreeData.value = response.data
      } catch (error) {
        console.error('获取菜单列表失败:', error)
        ElMessage.error('获取菜单列表失败')
      }
    }

    // 获取权限树数据
    const fetchPermissionTree = async () => {
      try {
        const response = await request.get('/permission/enabled')
        permissionTreeData.value = response.data || []
      } catch (error) {
        console.error('获取权限列表失败:', error)
        ElMessage.error('获取权限列表失败')
      }
    }

    // 获取角色已分配的菜单
    const fetchRoleMenus = async (roleId) => {
      try {
        const response = await request.get(`/role-menu/role/${roleId}/menus`)
        checkedMenuIds.value = response.data || []
      } catch (error) {
        console.error('获取角色菜单失败:', error)
        checkedMenuIds.value = []
      }
    }

    // 获取角色已分配的权限
    const fetchRolePermissions = async (roleId) => {
      try {
        const response = await request.get(`/role-permission/role/${roleId}`)
        checkedPermissionIds.value = response.data || []
      } catch (error) {
        console.error('获取角色权限失败:', error)
        ElMessage.error('获取角色权限失败')
        checkedPermissionIds.value = []
      }
    }

    // 获取叶子节点（只选中叶子节点，避免父子重复）
    const getLeafNodes = (nodes, selectedIds) => {
      const leafNodes = []
      
      const traverse = (nodeList) => {
        nodeList.forEach(node => {
          if (!node.children || node.children.length === 0) {
            // 叶子节点，检查是否被选中
            if (selectedIds.includes(node.id)) {
              leafNodes.push(node.id)
            }
          } else {
            // 有子节点，递归处理子节点（不管当前节点是否被选中）
            traverse(node.children)
          }
        })
      }
      
      traverse(nodes)
      return leafNodes
    }

    // 重置角色表单
    const resetRoleForm = () => {
      roleForm.id = null
      roleForm.roleName = ''
      roleForm.roleCode = ''
      roleForm.description = ''
      roleForm.status = 1
      
      if (roleFormRef.value) {
        roleFormRef.value.clearValidate()
      }
    }

    // 关闭角色对话框
    const closeRoleDialog = () => {
      roleDialogVisible.value = false
      resetRoleForm()
    }

    // 确认新增/编辑角色
    const confirmRole = async () => {
      if (!roleFormRef.value) return
      
      try {
        await roleFormRef.value.validate()
        roleLoading.value = true
        
        if (isEdit.value) {
          // 编辑角色
          await request.put(`/admin/roles/${roleForm.id}`, roleForm)
          ElMessage.success('编辑角色成功')
        } else {
          // 新增角色
          await request.post('/admin/roles', roleForm)
          ElMessage.success('新增角色成功')
        }
        
        closeRoleDialog()
        fetchRoles()
      } catch (error) {
        console.error('操作失败:', error)
        ElMessage.error(error.response?.data?.message || '操作失败')
      } finally {
        roleLoading.value = false
      }
    }

    // 新增角色
    const handleAdd = () => {
      isEdit.value = false
      resetRoleForm()
      roleDialogVisible.value = true
    }

    // 编辑角色
    const handleEdit = async (row) => {
      try {
        isEdit.value = true
        const response = await request.get(`/admin/roles/${row.id}`)
        const roleData = response.data
        
        roleForm.id = roleData.id
        roleForm.roleName = roleData.roleName
        roleForm.roleCode = roleData.roleCode
        roleForm.description = roleData.description
        roleForm.status = roleData.status
        
        roleDialogVisible.value = true
      } catch (error) {
        console.error('获取角色信息失败:', error)
        ElMessage.error('获取角色信息失败')
      }
    }

    // 分配菜单权限
    const handleAssignMenu = async (row) => {
      try {
        assignMenuForm.roleId = row.id
        assignMenuForm.roleName = row.roleName
        
        // 先获取菜单树数据
        await fetchMenuTree()
        
        // 确保菜单树数据加载完成后再获取角色已分配的菜单
        if (menuTreeData.value.length > 0) {
          await fetchRoleMenus(row.id)
        } else {
          ElMessage.error('菜单数据加载失败')
          return
        }
        
        // 打开对话框
        assignMenuVisible.value = true
      } catch (error) {
        console.error('准备分配菜单权限失败:', error)
        ElMessage.error('准备分配菜单权限失败')
      }
    }

    // 分配权限
    const handleAssignPermission = async (row) => {
      try {
        assignPermissionForm.roleId = row.id
        assignPermissionForm.roleName = row.roleName
        
        // 先获取权限树数据
        await fetchPermissionTree()
        
        // 确保权限树数据加载完成后再获取角色已分配的权限
        if (permissionTreeData.value.length > 0) {
          await fetchRolePermissions(row.id)
        } else {
          ElMessage.error('权限数据加载失败')
          return
        }
        
        // 打开对话框
        assignPermissionVisible.value = true
      } catch (error) {
        console.error('准备分配权限失败:', error)
        ElMessage.error('准备分配权限失败')
      }
    }

    // 对话框打开后的回调
    const onDialogOpened = async () => {
      // 等待DOM更新后设置选中的节点
      await nextTick()
      if (menuTreeRef.value && menuTreeData.value.length > 0) {
        // 先清空所有选中状态
        menuTreeRef.value.setCheckedKeys([])
        
        // 如果有已分配的菜单，则设置选中状态
        if (checkedMenuIds.value.length > 0) {
          // 只选中叶子节点，让Element Plus自动处理父节点状态
          const leafNodeIds = getLeafNodes(menuTreeData.value, checkedMenuIds.value)
          
          // 设置选中的节点
          menuTreeRef.value.setCheckedKeys(leafNodeIds)
        }
      }
    }

    // 关闭分配权限对话框
    const closeAssignDialog = () => {
      assignMenuVisible.value = false
      // 清空选中状态
      if (menuTreeRef.value) {
        menuTreeRef.value.setCheckedKeys([])
      }
      // 清空数据
      checkedMenuIds.value = []
      menuTreeData.value = []
      assignMenuForm.roleId = null
      assignMenuForm.roleName = ''
    }

    // 确认分配菜单权限
    const confirmAssignMenu = async () => {
      try {
        assignLoading.value = true
        
        // 验证roleId是否有效
        if (!assignMenuForm.roleId) {
          ElMessage.error('角色ID无效，请重新打开权限分配对话框')
          return
        }
        
        // 获取选中的菜单ID
        const checkedKeys = menuTreeRef.value.getCheckedKeys()
        const halfCheckedKeys = menuTreeRef.value.getHalfCheckedKeys()
        const allCheckedKeys = [...checkedKeys, ...halfCheckedKeys]
        
        if (allCheckedKeys.length === 0) {
          ElMessage.warning('请至少选择一个菜单')
          return
        }
        
        // 保存roleId，因为closeAssignDialog会清空它
        const currentRoleId = assignMenuForm.roleId
        
        // 分配菜单并自动绑定对应权限
        await request.post('/role-menu/assign-with-permissions', allCheckedKeys, {
          params: {
            roleId: currentRoleId
          }
        })
        
        ElMessage.success('分配菜单成功，已自动绑定对应权限')
        closeAssignDialog()
        
        // 刷新权限信息，让所有组件立即更新
        const { refreshPermissions } = usePermissions()
        await refreshPermissions()
        ElMessage.info('权限已更新，请查看最新菜单和按钮')
      } catch (error) {
        console.error('分配菜单权限失败:', error)
        ElMessage.error('分配菜单权限失败')
      } finally {
        assignLoading.value = false
      }
    }

    // 权限分配对话框打开后的回调
    const onPermissionDialogOpened = async () => {
      // 等待DOM更新后设置选中的节点
      await nextTick()
      if (permissionTreeRef.value && permissionTreeData.value.length > 0) {
        // 先清空所有选中状态
        permissionTreeRef.value.setCheckedKeys([])
        
        // 如果有已分配的权限，则设置选中状态
        if (checkedPermissionIds.value.length > 0) {
          // 只选中叶子节点，让Element Plus自动处理父节点状态
          const leafNodeIds = getLeafNodes(permissionTreeData.value, checkedPermissionIds.value)
          
          // 设置选中的节点
          permissionTreeRef.value.setCheckedKeys(leafNodeIds)
        }
      }
    }

    // 关闭分配权限对话框
    const closeAssignPermissionDialog = () => {
      assignPermissionVisible.value = false
      // 清空选中状态
      if (permissionTreeRef.value) {
        permissionTreeRef.value.setCheckedKeys([])
      }
      // 清空数据
      checkedPermissionIds.value = []
      permissionTreeData.value = []
      assignPermissionForm.roleId = null
      assignPermissionForm.roleName = ''
    }

    // 确认分配权限
    const confirmAssignPermission = async () => {
      try {
        assignPermissionLoading.value = true
        
        // 验证roleId是否有效
        if (!assignPermissionForm.roleId) {
          ElMessage.error('角色ID无效，请重新打开权限分配对话框')
          return
        }
        
        // 获取选中的权限ID
        const checkedKeys = permissionTreeRef.value.getCheckedKeys()
        const halfCheckedKeys = permissionTreeRef.value.getHalfCheckedKeys()
        const allCheckedKeys = [...checkedKeys, ...halfCheckedKeys]
        
        if (allCheckedKeys.length === 0) {
          ElMessage.warning('请至少选择一个权限')
          return
        }
        
        // 保存roleId，因为closeAssignPermissionDialog会清空它
        const currentRoleId = assignPermissionForm.roleId
        
        await request.post('/role-permission/assign', allCheckedKeys, {
          params: {
            roleId: currentRoleId
          }
        })
        
        ElMessage.success('分配权限成功')
        closeAssignPermissionDialog()
        
        // 刷新权限信息，让所有组件立即更新
        const { refreshPermissions } = usePermissions()
        await refreshPermissions()
        ElMessage.info('权限已更新，请查看最新权限配置')
      } catch (error) {
        console.error('分配权限失败:', error)
        ElMessage.error('分配权限失败')
      } finally {
        assignPermissionLoading.value = false
      }
    }

    // 删除角色
    const handleDelete = async (row) => {
      try {
        await ElMessageBox.confirm(`确定要删除角色 ${row.roleName} 吗？`, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
        
        await request.delete(`/admin/roles/${row.id}`)
        ElMessage.success('删除角色成功')
        fetchRoles()
      } catch (error) {
        if (error.response) {
          ElMessage.error(error.response.data?.message || '删除角色失败')
        }
        // 用户取消操作不显示错误
      }
    }

    onMounted(() => {
      fetchRoles()
    })

onMounted(() => {
  fetchRoles()
})
</script>

<style scoped>
.role-management {
  background: white;
  border-radius: 8px;
  padding: 20px;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  padding-bottom: 15px;
  border-bottom: 1px solid #e6e6e6;
}

.page-header h2 {
  margin: 0;
  color: #333;
}

.header-actions {
  display: flex;
  gap: 10px;
}

.table-container {
  margin-top: 20px;
}

.assign-menu-content {
  max-height: 400px;
  overflow-y: auto;
}

.role-info {
  margin-bottom: 15px;
  padding: 10px;
  background-color: #f5f7fa;
  border-radius: 4px;
  font-weight: bold;
  color: #606266;
}

.menu-tree {
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  padding: 10px;
  max-height: 300px;
  overflow-y: auto;
}

.tree-node-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}

.node-label {
  flex: 1;
  margin-right: 10px;
}

.node-type-tag {
  margin-left: 5px;
}

.menu-info {
  margin-bottom: 15px;
}

/* 权限分配相关样式 */
.assign-permission-content {
  max-height: 500px;
}

.permission-tree {
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  padding: 10px;
  max-height: 450px;
  overflow-y: auto;
}

.permission-tree-node-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  gap: 8px;
}

.permission-node-label {
  flex: 1;
  font-weight: 500;
  color: #303133;
}

.permission-node-type-tag {
  flex-shrink: 0;
}

.permission-code-tag {
  background: #f5f7fa;
  padding: 2px 6px;
  border-radius: 3px;
  font-family: 'Consolas', 'Monaco', monospace;
  font-size: 11px;
  color: #606266;
  flex-shrink: 0;
}
</style> 